package com.tiancheng.trade.order.channel.cmb;

import com.tiancheng.trade.order.bo.SubOrderRefundTotalBo;
import com.tiancheng.trade.order.channel.AbstractPayChannel;
import com.tiancheng.trade.order.enums.RefundStatusEnum;
import com.tiancheng.trade.commom.web.model.request.RefundDTO;
import com.tiancheng.trade.order.model.Order;
import com.tiancheng.trade.order.model.RefundOrders;
import com.tiancheng.trade.order.model.RefundOrdersDetail;
import com.tiancheng.trade.order.model.SubOrder;
import com.tiancheng.trade.order.vo.open.order.OpenRefundVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 招总行支付渠道
 *
 * @author likailun
 * @date 2021/4/20
 */
@Slf4j
@Service
public class CmbPayChannel extends AbstractPayChannel {


    @Override
    public RefundOrders generateRefunds(OpenRefundVO refundVO, Order order) {
        String[] subOrderIds = refundVO.getSubOrders().stream().map(OpenRefundVO.SubOrder::getSubOrderId).toArray(String[]::new);
        List<SubOrder> subOrders = subOrderService.findCanRefund(refundVO.getOrderId(), subOrderIds);

        // 子订单新提交的退款
        Map<String, Integer> applyRefundMap = refundVO.getSubOrders().stream().collect(Collectors.toMap(
                OpenRefundVO.SubOrder::getSubOrderId, x -> x.getRefundAmount() != null ? x.getRefundAmount() : 0));
        // 子订单所有退款汇总金额（包含本次提交的退款金额），包含已存在的退款记录状态为：IG、SC
        Map<String, SubOrderRefundTotalBo> refundTotalMap = this.checkRefundAmount(order, subOrders, applyRefundMap);
        String paymentId = orderIdHelper.getRefundPaymentId(order.getOrderSource(), refundVO.getUid());

        List<RefundOrdersDetail> refundOrdersDetails = new ArrayList<>();
        Integer suffix=1;
        for (SubOrder subOrder : subOrders) {
            RefundOrdersDetail refundOrdersDetail = new RefundOrdersDetail();
            refundOrdersDetail.setUid(refundVO.getUid());
            refundOrdersDetail.setRefundId(orderIdHelper.getRefund(order.getOrderSource(), refundVO.getUid()));
            refundOrdersDetail.setPaymentId(paymentId);
            refundOrdersDetail.setSubPaymentId((paymentId + String.format("%02d", suffix)));
            suffix++;
            refundOrdersDetail.setPayFlowId(order.getFlowId());
            refundOrdersDetail.setOrderId(subOrder.getOrderId());
            refundOrdersDetail.setSubOrderId(subOrder.getSubOrderId());
            refundOrdersDetail.setOrderSource(subOrder.getOrderSource());
            refundOrdersDetail.setMerchantCode(subOrder.getMerchantCode());
            refundOrdersDetail.setMerchantName(subOrder.getMerchantName());
            refundOrdersDetail.setProductCode(subOrder.getProductCode());
            refundOrdersDetail.setProductName(subOrder.getProductName());
            // 退款金额，如果未提交，默认使用子订单支付金额
            // 实际退款金额
            int refundAmount = applyRefundMap.get(subOrder.getSubOrderId()) != 0 ? applyRefundMap.get(subOrder.getSubOrderId()) : subOrder.getPayAmount();
            refundOrdersDetail.setRefundApplyAmount(refundAmount);
            refundOrdersDetail.setRefundAmount(refundAmount);
            refundOrdersDetail.setSubOrderAmount(subOrder.getSubOrderAmount());
            refundOrdersDetail.setSubOrderPayAmount(subOrder.getPayAmount());
            refundOrdersDetail.setDiscount(subOrder.getDiscount());
            refundOrdersDetail.setRefundStatus(RefundStatusEnum.ing.getCode());
            refundOrdersDetail.setRefundReason(refundVO.getRefundReason());
            refundOrdersDetail.setCreatedDt(refundVO.getCreateTime());
            refundOrdersDetail.setSubOrderStatus(subOrder.getSubOrderStatus());
            refundOrdersDetails.add(refundOrdersDetail);
        }
        // 总退款单
        final RefundOrders refundOrders = new RefundOrders();
        refundOrders.setRefundId(refundVO.getRefundId());
        refundOrders.setOrderId(refundVO.getOrderId());
        refundOrders.setPaymentId(paymentId);
        refundOrders.setPayFlowId(order.getFlowId());
        refundOrders.setUid(refundVO.getUid());
        refundOrders.setRefundApplyAmount(refundOrdersDetails.stream().mapToInt(RefundOrdersDetail::getRefundApplyAmount).sum());
        refundOrders.setRefundAmount(refundOrdersDetails.stream().mapToInt(RefundOrdersDetail::getRefundAmount).sum());
        refundOrders.setRefundStatus(RefundStatusEnum.ing.getCode());
        refundOrders.setRefundReason(refundVO.getRefundReason());
        refundOrders.setCreatedDt(LocalDateTime.now());
        refundOrders.setSubRefundOrders(refundOrdersDetails);
        return refundOrders;
    }
    @Override
    public RefundDTO createAndSubmit(OpenRefundVO refundVO, RefundOrders refundOrders) {
        final List<RefundOrdersDetail> refundOrdersDetails = refundOrders.getSubRefundOrders();
        RefundDTO refundDTO = new RefundDTO();
        refundDTO.setUid(refundVO.getUid());
        refundDTO.setPaymentId(refundOrdersDetails.get(0).getPaymentId());
        refundDTO.setPayFlowId(refundOrdersDetails.get(0).getPayFlowId());
        refundDTO.setAmount(refundOrdersDetails.stream().mapToInt(RefundOrdersDetail::getRefundApplyAmount).sum());

        refundDTO.setOrderAmount(refundOrdersDetails.stream().mapToInt(RefundOrdersDetail::getSubOrderAmount).sum());
        refundDTO.setDiscount(refundOrdersDetails.stream().mapToInt(RefundOrdersDetail::getPlatformDiscount).sum());
        refundDTO.setSubOrders(new ArrayList<>());

        refundOrdersDetails.forEach(refund -> {
            RefundDTO.SubOrderRefundDTO subOrderRefundDTO = new RefundDTO.SubOrderRefundDTO();
            subOrderRefundDTO.setSubOrderId(refund.getSubOrderId());
            subOrderRefundDTO.setSubPaymentId(refund.getSubPaymentId());
            subOrderRefundDTO.setAmount(refund.getRefundApplyAmount());
            subOrderRefundDTO.setOrderAmount(refund.getSubOrderAmount());
            subOrderRefundDTO.setDiscount(refund.getPlatformDiscount());
            refundDTO.getSubOrders().add(subOrderRefundDTO);
        });
        return refundDTO;
    }

}
